package com.wxproject.demo.Socket;

import com.alibaba.fastjson.JSON;

import com.wxproject.demo.Common.MyException.BusinessException;
import com.wxproject.demo.Common.exception.ResultEnum;

import com.wxproject.demo.Entity.VO.AllChatVO;
import com.wxproject.demo.Entity.VO.ChatMessageVO;
import com.wxproject.demo.Entity.VO.SocketVO;
import com.wxproject.demo.Entity.VO.UserNameVO;
import com.wxproject.demo.Service.ChatService;
import com.wxproject.demo.Utils.DateUtils;
import com.wxproject.demo.Utils.RedisUtil;
import com.wxproject.demo.Utils.SnowFlake;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;


/**
 * @author zqf
 * @date 2021/4/5 22:10
 * @description
 */

@Component
@ServerEndpoint("/websocket/{params}")
@Log4j2
public class WebSocket {
    private static ChatService chatService;

    @Autowired
    private void setChatService(ChatService chatService) {
        this.chatService = chatService;
    }

    //String为用户名，key就是用户名对应的Session
    private final static Map<String, Session> sessionPool = new HashMap<String, Session>();
    // 使用map来收集session，key为roomName，value为同一个房间的用户集合
    private static final Map<String, Set<Session>> rooms = new ConcurrentHashMap<>();
    //缓存session对应的用户
    private static final Map<String, String> users = new ConcurrentHashMap<>();


    @OnOpen
    public void onOpen(Session session, @PathParam(value = "params") String params) throws UnsupportedEncodingException {
        String[] strArr = params.split("-");
        String username = java.net.URLDecoder.decode(strArr[0], "UTF-8");
        String roomId = java.net.URLDecoder.decode(strArr[1], "UTF-8");
//        String roomName = chatService.getRoomNameByTypeId(typeId);
        String roomName = chatService.getRoomNameByRoomId(roomId);
        sessionPool.put(username, session);
        //如果没有房间，就查询房间列表
        if (rooms.size() == 0) {
            List<String> roomList = chatService.getAllRoom();
            for (int i = 0; i < roomList.size(); i++) {
                rooms.put(roomList.get(i), new HashSet<>());
            }
        }
        //如果存在房间，直接添加用户到该房间
        if (rooms.containsKey(roomName)) {
            rooms.get(roomName).add(session);
        }
        if (!rooms.containsKey(roomName)) {
            Integer res = chatService.getRoomName(roomName);
            if (res != 0) {
                rooms.put(roomName, new HashSet<>());
            }
        }
        users.put(session.getId(), username);
        //向上线的人发送当前房间在线列表
        SocketVO s = new SocketVO();
        Set<String> userList = new HashSet<>();
        for (Session session1 : rooms.get(roomName)) {
            String usernameS = users.get(session1.getId());
            userList.add(usernameS);
        }
        s.setUserList(userList);
        String msg = JSON.toJSONString(s);
        for (Session session1 : rooms.get(roomName)) {
            if (session1.isOpen()) {
                session1.getAsyncRemote().sendText(msg);
            }
        }
    }

    @OnClose
    public void onClose(@PathParam("params") String params, Session session) throws UnsupportedEncodingException {
        String[] strArr = params.split("-");
        String roomId = java.net.URLDecoder.decode(strArr[1], "UTF-8");
        String roomName = chatService.getRoomNameByRoomId(roomId);
        rooms.get(roomName).remove(session);
    }

    @OnMessage
    public void onMessage(String message) {
        System.out.println("收到客户端消息:" + message);
    }

    // 此为全体消息
    public void sendAllMessage(String message, String roomName, String username,String avatarUrl) {
        AllChatVO allChatVO = new AllChatVO();
        allChatVO.setMsg(message);
        allChatVO.setUsername(username);
        allChatVO.setRoomName(roomName);
        allChatVO.setSenderAvatarUrl(avatarUrl);
        allChatVO.setDate(DateUtils.getMinutesDate());
        String msg = JSON.toJSONString(allChatVO);
        System.out.println("testMessage：" + message + " " + roomName + " " + username);
        try {
            for (Session session1 : rooms.get(roomName)) {
                if (session1.isOpen()) {
                    session1.getAsyncRemote().sendText(msg);
                }
            }
        } catch (Exception e) {
            log.info("聊天室不存在", e);
            throw new BusinessException(ResultEnum.EMPTY_CHAT_ROOM);
        }
    }

    // 此为单点消息
    public void sendOneMessage(String senderName, String receiverName, String message) {
        UserNameVO userNameVO = new UserNameVO();
        userNameVO.setSenderName(senderName);
        userNameVO.setReceiverName(receiverName);
        userNameVO.setMessage(message);
        String senderAvatarUrl = RedisUtil.hmget("userInfo-"+userNameVO.getSenderName()).get("avatarUrl").toString();
        userNameVO.setSenderAvatarUrl(senderAvatarUrl);
        String receiverAvatarUrl = RedisUtil.hmget("userInfo-"+userNameVO.getReceiverName()).get("avatarUrl").toString();
        userNameVO.setReceiverAvatarUrl(receiverAvatarUrl);
        for (Map.Entry<String, Set<Session>> entry : rooms.entrySet()) {
            Set<Session> value = entry.getValue();
            for (Session str : value) {
                if (users.get(str.getId()).equals(senderName)) {
                    try {
                        String msg = JSON.toJSONString(userNameVO);
                        str.getAsyncRemote().sendText(msg);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                if (users.get(str.getId()).equals(receiverName)) {
                    try {
                        String msg = JSON.toJSONString(userNameVO);
                        str.getAsyncRemote().sendText(msg);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}